// Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use anyhow::Context;
use clap::Parser;
use indicatif::MultiProgress;
use log::trace;

use crate::{build::BuildContext, commands::BuildGraphArgs, database::mirror::Mirrors, FerriumCommand};

#[derive(Debug, Parser)]
pub struct InstallCommand {
    #[command(flatten)]
    build_graph_args: BuildGraphArgs,
    /// Reinstall all specified packages
    #[arg(long)]
    reinstall: bool,
}

impl FerriumCommand for InstallCommand {
    async fn run(self, multi_progress: MultiProgress) -> anyhow::Result<()> {
        let (mut dep_graph, toolchain_name, mut system_config) = self.build_graph_args.build_graph().await?;
        let sorted_ids = dep_graph.verify(true)
            .context("failed to resolve specs")?;

        let mirrors = Mirrors::fetch_index_configs(system_config.default_mirror_urls().map(|s| s.as_str()))
            .await;
        if mirrors.is_empty() { anyhow::bail!("no mirrors found"); }

        let toolchain_config = system_config.toolchains.0.get_mut(&toolchain_name).unwrap();
        let mut build_context = BuildContext::new(
            dep_graph,
            sorted_ids,
            std::mem::take(toolchain_config),
            mirrors,
            self.reinstall,
        ).await?;
        
        let mut task_info = Vec::new();
        build_context.dump_task_info(&mut task_info)?;
        let task_info = String::from_utf8(task_info)?;
        trace!("\n{}", task_info);
        build_context.build_all(multi_progress).await?;     

        Ok(())
    }
}
